﻿using System.Collections.Generic;
using System;
using System.Text;

namespace Ex03.GarageLogic
{
    /// <summary>
    /// This class will hold all the garage clients and will have all
    /// the actions that can be perform on them
    /// </summary>
    public class Garage
    {
        private const GarageClient k_GarageClientNotFound = null;
        private List<GarageClient> m_Clients = new List<GarageClient>();
        
        /// <summary>
        /// a constructor
        /// </summary>
        public Garage()
        {
        }

        /// <summary>
        /// This method will add a new GarageClient
        /// </summary>
        /// <param name="i_GarageClient">The new client</param>
        public void AddNewGarageClient(GarageClient i_GarageClient)
        {
            m_Clients.Add(i_GarageClient);
        }

        /// <summary>
        /// This method return all the plate numbers of vehicles currently on the garage
        /// </summary>
        /// <returns>A list string of plate numbers of vehicles in the garage</returns>
        public List<string> GetVehiclesPlateNumberCurrentlyInGarage()
        {
            List<string> resultVehiclesPlateNumber = new List<string>();
            
            foreach (GarageClient garageClient in m_Clients)
            {
                resultVehiclesPlateNumber.Add(garageClient.Vehicle.PlateNumber);                
            }

            return resultVehiclesPlateNumber;
        }

        /// <summary>
        /// This method return all the plate numbers of vehicles currently on the garage
        /// according to a plate number
        /// </summary>
        /// <param name="i_ProcessStatus">The status of the Vehicles we are looking for</param>
        /// <returns>A list of plate numbers of vehicles currently in the garage who's status is same as 
        /// input
        /// </returns>
        public List<string> GetVehiclesPlateNumberCurrentlyInGarageByPorcessStatus(GarageClient.eProcessStatus i_ProcessStatus)
        {
            List<string> filteredVehiclesPlateNumberInGarage = new List<string>();

            foreach (GarageClient garageClient in m_Clients)
            {
                if (garageClient.ProcessStatus == i_ProcessStatus)
                {
                    filteredVehiclesPlateNumberInGarage.Add(garageClient.Vehicle.PlateNumber);
                }
            }
            
            return filteredVehiclesPlateNumberInGarage;
        }

        /// <summary>
        /// Set a new status for the Garage Client vehicle
        /// </summary>
        /// <param name="i_VehiclePlateNumber">The Vehicle Plate Number</param>
        /// <param name="i_NewStatus">The new status</param>
        public void ChangeGarageClientStatus(string i_VehiclePlateNumber, GarageClient.eProcessStatus i_NewStatus)
        {
            GarageClient clientToChangeStatusOf = GetGarageClientByVehiclePlateNumber(i_VehiclePlateNumber);
            if (clientToChangeStatusOf == k_GarageClientNotFound)
            {
                throw new KeyNotFoundException("No vehicle with this plate number exists in garage");
            }

            clientToChangeStatusOf.ProcessStatus = i_NewStatus;
        }

        /// <summary>
        /// Let you inflate a vehicle Wheels
        /// </summary>
        /// <param name="i_PlateNumber">
        /// The Vehicle who's Wheels are needed to be inflate
        /// <remarks>
        /// If i_PlateNumber is not found will throw KeyNotFoundException
        /// </remarks>
        /// </param>
        public void FullyInflateAllTiresOfVehicle(string i_PlateNumber)
        {
            float amountToInflateToFull;
            GarageClient vehicleOwner = GetGarageClientByVehiclePlateNumber(i_PlateNumber);

            if (vehicleOwner == k_GarageClientNotFound)
            {
                throw new KeyNotFoundException("No vehicle with this plate number exists in garage");
            }
            
            foreach(Wheel wheel in vehicleOwner.Vehicle.Wheels)
            {
                amountToInflateToFull = wheel.MaxAirPressure - wheel.CurrentAirPressure;
                wheel.InflateTire(amountToInflateToFull);
            }
        }

        /// <summary>
        /// Let you fuel a Vehicle
        /// </summary>
        /// <param name="i_PlateNumber">
        /// The Vehicle we want to fuel
        /// <remarks>
        /// If i_PlateNumber is not found will throw KeyNotFoundException
        /// </remarks>
        /// </param>
        /// <param name="i_FuelType"> The fuel type</param>
        /// <param name="i_AmountToFillInLitres">The amount to fuel</param>
        public void RefuelFuelPoweredVehicle(string i_PlateNumber, FuelPoweredVehicle.eFuelType i_FuelType, float i_AmountToFillInLitres)
        {
            FuelPoweredVehicle needsRefuel = GetGarageClientByVehiclePlateNumber(i_PlateNumber).Vehicle as FuelPoweredVehicle;

            if (needsRefuel == null)
            {
                throw new ArgumentException("Can't refuel a vehicle that is not fuel powered");
            }

            needsRefuel.Refuel(i_AmountToFillInLitres, i_FuelType);
        }

        /// <summary>
        /// Let you charge a Vehicle
        /// </summary>
        /// <param name="i_PlateNumber">
        /// The Vehicle we want to charge
        /// <remarks>
        /// If i_PlateNumber is not found will throw KeyNotFoundException
        /// </remarks>
        /// </param>
        /// <param name="i_AmountToChargeInMinutes">The amount to charge in minutes</param>
        public void ChargeElerctricPoweredVehicle(string i_PlateNumber, float i_AmountToChargeInMinutes)
        {
            ElectricPoweredVehicle needsCharging = GetGarageClientByVehiclePlateNumber(i_PlateNumber).Vehicle as ElectricPoweredVehicle;

            if (needsCharging == null)
            {
                throw new ArgumentException("Can't charge a vehicle that is not electric powered");
            }

            needsCharging.ChargeBattery(i_AmountToChargeInMinutes);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="i_PlateNumber"></param>
        /// <returns></returns>
        public string GettFullClientAndVehicleDetails(string i_PlateNumber)
        {
            GarageClient toGetDetailsOf = GetGarageClientByVehiclePlateNumber(i_PlateNumber);

            return toGetDetailsOf.ToString();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="i_PlateNumber">
        /// The client's vehicle's plate number
        /// <remarks>
        /// If i_PlateNumber is not found will throw KeyNotFoundException
        /// </remarks>
        /// </param>
        /// <returns>The garage client we are looking for</returns>
        public GarageClient GetGarageClientByVehiclePlateNumber(string i_PlateNumber)
        {
            GarageClient resultGarageClient = null;

            foreach (GarageClient garageClient in m_Clients)
            {
                if (garageClient.Vehicle.PlateNumber == i_PlateNumber)
                {
                    resultGarageClient = garageClient;
                }
            }

            if (resultGarageClient == k_GarageClientNotFound)
            {
                throw new KeyNotFoundException("No vehicle with this plate number exists in garage");
            }

            return resultGarageClient;
        }       
    }
}
